package com.cskaoyan.javase.array._6call;

import jdk.nashorn.internal.objects.NativeNumber;

import javax.xml.transform.sax.SAXTransformerFactory;
import java.util.Arrays;

/**
 * 何为方法的传值问题？
 * 调用方法时，我们需要传递实参给方法，在方法内部有可能会改变这些实参的值。
 * 那么方法执行完毕后，这些实参的值在原先的方法中会怎么变呢？这就是方法的传值问题。
 *
 * 以下两种方法的传值方式，它们是用于解释方法传参的两个情况：
 *      1.值传递（call by value），指的是调用方法时，传入的是实参的拷贝而不是实参本身。
 *          如果Java是值传递的，那么方法改变的是实参拷贝的值，原本实参的值是不会被改变的。
 *      2.引用传递（call by reference），指的是调用方法时，传入的是实参变量的地址，也就是实参本身。
 *          如果Java是引用传递的，方法改变的是实参本身的值，方法结束后，原本实参变量的值会随直改变。
 * 那么接下来，验证一下，Java的方法究竟是何种传值方式呢？（非常重要的问题）
 * 首先，分两种情况验证：
 *      1.基本数据类型的实参变量传参
 *          通过一个将实参int类型数据变为原先2倍但是失败的方法
 *          说明：
 *          至少对于Java基本数据类型来说，Java是值传递的
 *
 *      2.引用数据类型的实参变量传参
 *          通过一个将实参int数组类型中的元素数据变为原先2倍成功的方法
 *          说明：
 *          对于Java引用数据类型来说，Java是引用传递的
 *
 *  以上是关于Java方法传值问题的，经典错误。
 *  实际上Java只有值传递，没有任何引用传递。
 *
 *  通过一系列的测试,我们知道了Java方法的传值方式是值传递的
 *  那么就可以得出以下结论:
 *  Java方法对方法参数能做什么？
 *      1.任何Java方法，都不可能修改另外一个方法中的局部变量，包括:
 *          a.其它方法中的基本数据类型变量
 *          b.其它方法中的引用数据类型的引用
 *      可以想象，如果上述修改能够成立，就违背了局部变量的设计原则。
 *
 *      2.（重点）Java方法可以修改对象中元素的取值(改变对象的状态)，因为方法得到的是引用的拷贝，拷贝引用仍然指向原先引用指向的对象。
 *
 *
 * @since 09:42
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        int num = 10;
        doubleIntValue(num);
        System.out.println(num);
        System.out.println("----------------");
        int[] arr = {1, 2, 3};
        doubleIntArrElement(arr);
        System.out.println(Arrays.toString(arr));

        System.out.println("-----------------");
        int[] arr1 = {666, 666, 666};
        int[] arr2 = {777, 777, 777};
        System.out.println("交换之前arr1 = " + arr1);
        System.out.println("交换之前arr2 = " + arr2);
        /*
            分析:
                1.如果交换成功
                    说明方法得到的是引用本身
                    所以方法的传值是引用传递的

                2.如果交换失败
                    说明方法得到的是引用的拷贝
                    交换成功的是引用的拷贝
                    而原先的引用不可能交换成功
                    Java是值传递的
         */
        swapIntArrReference(arr1, arr2);
        System.out.println("交换之后arr1 = " + arr1);
        System.out.println("交换之后arr2 = " + arr2);
    }

    // 将一个int类型实参变为原先的2倍
    public static void doubleIntValue(int num) {
        num *= 2;
    }

    // 将一个int类型的数组元素取值变为原先的2倍
    public static void doubleIntArrElement(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            arr[i] *= 2;
        }
    }

    // 将两个数组的引用交换
    public static void swapIntArrReference(int[] arr1, int[] arr2) {
        int[] temp = arr1;
        arr1 = arr2;
        arr2 = temp;
        System.out.println("交换之中arr1 = " + arr1);
        System.out.println("交换之中arr2 = " + arr2);
    }
}
